#ifndef xpack_net_private_base_net
#define xpack_net_private_base_net
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::net_private_base_net::inc
#include"define/base_type.hpp"
#include"dumb/disable_copy.hpp"
#include"macro/xstruct.hpp"
#include"net/private/define.hpp"
#pragma pop_macro("xuser")

namespace mixc::net_private_base_net::inc{
    extern void set_read_timeout(ixx fd, u64 millisecond);
    extern u64  get_read_timeout(ixx fd);

    extern void set_write_timeout(ixx fd, u64 millisecond);
    extern u64  get_write_timeout(ixx fd);

    extern inc::sock_type_t get_sock_type(ixx fd);
}

namespace mixc::net_private_base_net::origin{
    xstruct(
        xname(base_net),
        xpubb(inc::disable_copy),
        xprof(m_fd, ixx)
    )
    public:
        xprops()
            xpubgetx(is_valid, bool){
                xr{ return xthe.m_fd > 0; }
            };

            xpubgetx(sock_type, inc::sock_type_t){
                xr{ return inc::get_sock_type(xthe.m_fd); }
            };

            xpubgetx(is_closed, bool){
                xr{ return xthe.m_fd == 0 or inc::get_sock_type(xthe.m_fd) == inc::sock_type_t::not_exist; }
            };

            xpubget_pubsetx(read_timeout, u64){
                xr{ return inc::get_read_timeout(xthe.m_fd); }
                xw{ inc::set_read_timeout(xthe.m_fd, value); }
            };

            xpubget_pubsetx(write_timeout, u64){
                xr{ return inc::get_write_timeout(xthe.m_fd); }
                xw{ inc::set_write_timeout(xthe.m_fd, value); }
            };
        $

        xprops_operator()

    public:
        base_net() : m_fd(-1) {}
        base_net(base_net && self) : m_fd(self.m_fd){
            self.m_fd               = -1;
        }

    protected:
        using final_t = the_t;

       ~base_net(){
           this->close();
        }

        bstate_t open(inc::sock_type_t type, inc::reuse_address_t mode = inc::reuse_address_t::system_default) const;

        bstate_t bind(inc::ipv4 ip, u16 port) const;

        bstate_t bind(inc::ipv6 ip, u16 port) const;

        bstate_t open_with_bind(inc::sock_type_t type, inc::ipv4 ip, u16 port, inc::reuse_address_t mode = inc::reuse_address_t::system_default) const;

        bstate_t open_with_bind(inc::sock_type_t type, inc::ipv6 ip, u16 port, inc::reuse_address_t mode = inc::reuse_address_t::system_default) const;

    public:
        bstate_t close() const;

        bstate_t close_forcedly() const;

        ::handler lend() const {
            return ::handler{ m_fd };
        }
    private:
        bstate_t close_core(bool forcedly) const;
    $

    using inc::sock_type_t;
}

#endif

xexport_space(mixc::net_private_base_net::origin)
